<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<script>
		var mathJaxQueue = [];
		
		// Disables global typesetting and messages on startup, adds queue for
		// asynchronous rendering while MathJax is loading
		window.MathJax =
		{
			skipStartupTypeset: true,
			messageStyle: 'none',
			AuthorInit: function ()
			{
				MathJax.Hub.Register.StartupHook('Begin', function()
				{
					for (var i = 0; i < mathJaxQueue.length; i++)
					{
						MathJax.Hub.Queue(['Typeset', MathJax.Hub, mathJaxQueue[i]]);
					}
				});
		    }
		};
	
		// Adds global enqueue method for async rendering
		window.MathJaxRender = function(container)
		{
			// Initial rendering when MathJax finished loading
			if (typeof(MathJax) !== 'undefined' && typeof(MathJax.Hub) !== 'undefined')
			{
				MathJax.Hub.Queue(['Typeset', MathJax.Hub, container]);
			}
			else
			{
				mathJaxQueue.push(container);
			}
		}
	</script>
    <script src="https://cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
	<script>
		var urlParams = (function(url)
		{
			var result = new Object();
			var params = window.location.search.slice(1).split('&');
			
			for (var i = 0; i < params.length; i++)
			{
				idx = params[i].indexOf('=');
				
				if (idx > 0)
				{
					result[params[i].substring(0, idx)] = params[i].substring(idx + 1);
				}
			}
			
			return result;
		})(window.location.href);
		
		// Removes unused dependencies
		urlParams['analytics'] = '0';
		urlParams['picker'] = '0';
		urlParams['gapi'] = '0';
		urlParams['db'] = '0';
		
		// Public global variables
		var MAX_REQUEST_SIZE = 10485760;
		var MAX_AREA = 10000 * 10000;

		// Paths and files
		var STENCIL_PATH = 'stencils';
		var SHAPES_PATH = 'shapes';
		var IMAGE_PATH = 'images';
		// Path for images inside the diagram
		var GRAPH_IMAGE_PATH = 'img';
		var STYLE_PATH = 'styles';
		var CSS_PATH = 'styles';
		
		// Directory for i18 files and basename for main i18n file
		var RESOURCES_PATH = 'resources';
		var RESOURCE_BASE = RESOURCES_PATH + '/dia';
	
		// Specifies connection mode for touch devices (at least one should be true)
		var isLocalStorage = false;
		var uiTheme = null;

		// Sets the base path, the UI language via URL param and configures the
		// supported languages to avoid 404s. The loading of all core language
		// resources is disabled as all required resources are in grapheditor.
		// properties. Note that in this example the loading of two resource
		// files (the special bundle and the default bundle) is disabled to
		// save a GET request. This requires that all resources be present in
		// the special bundle.
		var mxLoadResources = false;
		var mxLanguage = 'en'
		var geBasePath = 'js';
		var mxBasePath = 'mxgraph';

		function render(data)
		{
			mxConstants.SHADOWCOLOR = '#000000';
			mxConstants.SHADOW_OPACITY = 0.25;

			var graph = new Graph(document.getElementById('graph'));
			graph.foldingEnabled = false;
			graph.setEnabled(false);
			
			if (data.math)
			{
				mxClient.NO_FO = true;
			}

			var xmlDoc = mxUtils.parseXml(data.xml);
			var codec = new mxCodec(xmlDoc);
			codec.decode(xmlDoc.documentElement, graph.getModel());

			// Handles PDF output where the output should match the page format if the page is visible
			if (data.math && data.format == 'pdf' && xmlDoc.documentElement.getAttribute('page') == '1')
			{
				graph.pageVisible = true;

				var pw = xmlDoc.documentElement.getAttribute('pageWidth');
				var ph = xmlDoc.documentElement.getAttribute('pageHeight');
				
				if (pw != null && ph != null)
				{
					graph.pageFormat = new mxRectangle(0, 0, parseFloat(pw), parseFloat(ph));
				}
				
				var ps = xmlDoc.documentElement.getAttribute('pageScale');
				
				if (ps != null)
				{
					graph.pageScale = ps;
				}
				
				graph.getPageSize = function()
				{
					return new mxRectangle(0, 0, this.pageFormat.width * this.pageScale,
							this.pageFormat.height * this.pageScale);
				};
				
				graph.getPageLayout = function()
				{
					var size = (this.pageVisible) ? this.getPageSize() : this.scrollTileSize;
					var bounds = this.getGraphBounds();
					
					if (bounds.width == 0 || bounds.height == 0)
					{
						return new mxRectangle(0, 0, 1, 1);
					}
					else
					{
						// Computes untransformed graph bounds
						var x = bounds.x / this.view.scale - this.view.translate.x;
						var y = bounds.y / this.view.scale - this.view.translate.y;
						var w = bounds.width / this.view.scale;
						var h = bounds.height / this.view.scale;
						
						var x0 = Math.floor(x / size.width);
						var y0 = Math.floor(y / size.height);
						var w0 = Math.ceil((x + w) / size.width) - x0;
						var h0 = Math.ceil((y + h) / size.height) - y0;
						
						return new mxRectangle(x0, y0, w0, h0);
					}
				};

				// Fits the number of background pages to the graph
				graph.view.getBackgroundPageBounds = function()
				{
					var layout = this.graph.getPageLayout();
					var page = this.graph.getPageSize();
					
					return new mxRectangle(this.scale * (this.translate.x + layout.x * page.width),
							this.scale * (this.translate.y + layout.y * page.height),
							this.scale * layout.width * page.width,
							this.scale * layout.height * page.height);
				};
			}
			else if (data.crop)
			{
				var b = graph.getGraphBounds();
				graph.view.setTranslate(-b.x, -b.y);
			}
			else if (data.w != null && data.h != null)
			{
				var b = graph.getGraphBounds();
				var s = Math.floor(Math.min(data.w / b.width, data.h / b.height) * 100) / 100;
				graph.view.scaleAndTranslate(s, (data.w - b.width * s) / 2 / s - b.x,
						(data.h - b.height * s) / 2 / s - b.y);
			}
			
			if (data.math)
			{
				window.MathJaxRender(graph.container);
				
				// Asynchronous callback when MathJax has finished
				window.MathJax.Hub.Queue(function ()
				{
					if (typeof window.callPhantom === 'function')
					{
						window.callPhantom();
					}
				});
			}

			var bounds = (graph.pageVisible) ? graph.view.getBackgroundPageBounds() : graph.getGraphBounds();
			var bg = xmlDoc.documentElement.getAttribute('background');
			
			// Apply background color for direct export
			if (data.format == 'jpg' && bg == 'none')
			{
				bg = '#ffffff';
			}
			
			if (graph.pageVisible)
			{
				document.body.style.width = bounds.width + 'px';
				document.body.style.height = bounds.height + 'px';
			}
			
			document.body.style.backgroundColor = bg || '#ffffff';

			// SVG not needed for math export
			var svg = (data.math) ? '' : mxUtils.getXml(graph.getSvg());
			
			return {width: bounds.width, height: bounds.height, bg: bg, svg: svg};
		};
	</script>
	<script src="js/app.min.js"></script>
</head>
<body style="margin:0px;">
	<div id="graph"></div>
</body>
</html>
